package org.ssssssss.magicapi.core.web;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import jdk.nashorn.internal.parser.JSONParser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.ssssssss.magicapi.core.config.Constants;
import org.ssssssss.magicapi.core.config.MagicConfiguration;
import org.ssssssss.magicapi.core.exception.InvalidArgumentException;
import org.ssssssss.magicapi.core.interceptor.Authorization;
import org.ssssssss.magicapi.core.model.*;
import org.ssssssss.magicapi.core.resource.FileResource;
import org.ssssssss.magicapi.core.resource.Resource;
import org.ssssssss.magicapi.core.service.MagicDynamicRegistry;
import org.ssssssss.magicapi.core.service.MagicResourceService;
import org.ssssssss.magicapi.utils.DataTablesUtils;
import org.ssssssss.magicapi.utils.IoUtils;
import org.ssssssss.magicapi.utils.MysqlMapToJava;
import org.w3c.dom.ls.LSOutput;

import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.function.Function;

public class FreeMarkerController extends MagicController implements MagicExceptionHandler {

    private final MagicResourceService service;

    public FreeMarkerController(MagicConfiguration configuration) {
        super(configuration);
        this.service = MagicConfiguration.getMagicResourceService();
    }

    @GetMapping("/hello")
    @ResponseBody
    public JsonBean<String> testController(){
        return new JsonBean<>("hhh... hello");
    }

    /**
     * 根据表名得到表中每个字段的描述
     * @param tableName
     * @return
     */
    @GetMapping("/describes/{tableName}")
    @ResponseBody
    public JsonBean<List<TableDefinition>> getTableDescribes(@PathVariable("tableName") String tableName){
        List<TableDefinition> definition = service.getTableDefinition(tableName);
        return new JsonBean<>(definition);
    }

    /**
     * 返回数据库中所有表的名称
     * @return
     */
    @GetMapping("/tablelist")
    @ResponseBody
    public JsonBean<List<String>> getTablesList(){
        List<String> tables = service.getTableNames();
        return new JsonBean<>(tables);
    }

    // 自己的新建分组的功能
    @PostMapping("/resource/folder/mysave")
    @ResponseBody
    public JsonBean<String> mySaveFolder(@RequestBody Group group, HttpServletRequest request) {
        isTrue(allowVisit(request, Authorization.SAVE, group), PERMISSION_INVALID);
        Resource resource = service.getResource();
        if(resource instanceof FileResource){
            isTrue(resource.exists(), FILE_PATH_NOT_EXISTS);
        }
        if (service.saveGroup(group)) {
            return new JsonBean<>(group.getId());
        }
        return new JsonBean<>((String) null);
    }

    // 自己的保存api
    @PostMapping("/resource/file/{folder}/saves")
    @ResponseBody
    public JsonBean<String> saveFile(@PathVariable("folder") String folder, String auto, HttpServletRequest request) throws IOException {
         auto = "0";
         //将request中的参数解析成四部分：ApiInfo、mysql条件列表、mysql返回参数列表、表名
        byte[] mybytes = IoUtils.bytes(request.getInputStream());
        String s = new String(mybytes, StandardCharsets.UTF_8);
        Map map = JSON.parseObject(s, Map.class);
        String ent = map.get("p1").toString();  // ApiInfo 的信息
        String p2 = map.get("p2").toString();  // p2 是条件参数
        String p3 = map.get("p3").toString();  // p3 是查询的列名
        String table_name = map.get("p4").toString();  // 表名

        // 将入参和返回参数填入模板中，然后返回处理好的脚本
        String p_script = service.processScript(p2, p3, table_name);

        //后面是原本的逻辑，没有改动
        byte[] bytes = ent.getBytes(StandardCharsets.UTF_8);
         //byte[] bytes = IoUtils.bytes(request.getInputStream());
         MagicEntity entity = configuration.getMagicDynamicRegistries().stream()
                .map(MagicDynamicRegistry::getMagicResourceStorage)
                .filter(it -> Objects.equals(it.folder(), folder))
                .findFirst()
                .orElseThrow(() -> new InvalidArgumentException(GROUP_NOT_FOUND))
                .read(bytes);

         entity.setScript(p_script);
         isTrue(allowVisit(request, Authorization.SAVE, entity), PERMISSION_INVALID);
         // 自动保存的代码，和旧版代码对比，如果一致，则不保存，直接返回。
         if(entity.getId() != null && "1".equals(auto)){
            MagicEntity oldInfo = service.file(entity.getId());
            if(oldInfo != null && Objects.equals(oldInfo, entity)){
                return new JsonBean<>(entity.getId());
            }
        }
        if (MagicConfiguration.getMagicResourceService().saveFile(entity)) {
            return new JsonBean<>(entity.getId());
        }
        return new JsonBean<>(null);
    }

    @PostMapping("/resource/file/saves")
    @ResponseBody
    public JsonBean<String> testFile(HttpServletRequest request) throws IOException {

        byte[] bytes = IoUtils.bytes(request.getInputStream());
        String s = new String(bytes, StandardCharsets.UTF_8);
        Map map = JSON.parseObject(s, Map.class);

        for (Object obj : map.keySet()){
            System.out.println("key为："+obj+"值为："+map.get(obj));
        }
        String p2 = map.get("p2").toString();
        List<String> strings = JSONObject.parseArray(p2, String.class);
        for (String lls:strings) {
            System.out.println(lls);
        }

        return new JsonBean<>(null);
    }

    //根据文件id得到entity实体
    @GetMapping("/resource/getfile/{id}")
    @ResponseBody
    public JsonBean<MagicEntity> detail(@PathVariable("id") String id) {
        MagicEntity entity = MagicConfiguration.getMagicResourceService().file(id);
        if (entity == null)
            return new JsonBean<>(null);
        return new JsonBean<>(entity);
    }

    //根据文件id得到Group信息
    @GetMapping("/myresource/getgroup/{fileId}")
    @ResponseBody
    public JsonBean<List<Group>> findGroupbyFileid(@PathVariable String fileId){
        List<Group> groupsByFileId = service.getGroupsByFileId(fileId);
        return new JsonBean<>(groupsByFileId);
    }

    //传回一个id，来判断它是组还是文件
    @GetMapping("/myresource/isgroup/{id}")
    @ResponseBody
    public JsonBean<Boolean> validId(@PathVariable String id){
        if (service.getGroup(id)==null){
            return new JsonBean<>(false);
        }
        return new JsonBean<>(true);
    }

    //新建组的时候，调用的是这个
    @PostMapping("/resource/entity/save")
    @ResponseBody
    public JsonBean<String> saveEntity(HttpServletRequest request) throws IOException {
        String folder = "api";
        System.out.println(request.toString());
        byte[] bytes = IoUtils.bytes(request.getInputStream());
        MagicEntity entity = configuration.getMagicDynamicRegistries().stream()
                .map(MagicDynamicRegistry::getMagicResourceStorage)
                .filter(it -> Objects.equals(it.folder(), folder))
                .findFirst()
                .orElseThrow(() -> new InvalidArgumentException(GROUP_NOT_FOUND))
                .read(bytes);
        System.out.println(entity.toString());
        return new JsonBean<>((String) null);
    }

    //初始化所有资源的
    @GetMapping("/myresource")
    @ResponseBody
    public JsonBean<Map<String, TreeNode<Attributes<Object>>>> resources(HttpServletRequest request) {
        Map<String, TreeNode<Group>> tree = service.tree();
        Map<String, TreeNode<Attributes<Object>>> result = new HashMap<>();
        tree.forEach((key, value) -> {
            TreeNode<Attributes<Object>> node = process(value, request);
            List<TreeNode<Attributes<Object>>> groups = node.getChildren();
            if(groups.size() > 0){
                List<TreeNode<Attributes<Object>>> nodes = groups.get(0).getChildren();
                configuration.getMagicDynamicRegistries().stream()
                        .filter(it -> it.getMagicResourceStorage().folder().equals(key))
                        .findFirst()
                        .map(MagicDynamicRegistry::defaultMappings)
                        .ifPresent(mappings -> {
                            for (MagicEntity mapping : mappings) {
                                nodes.add(new TreeNode<>(mapping));
                            }
                        });
            }
            result.put(key, node);
        });
        return new JsonBean<>(result);
    }

    private TreeNode<Attributes<Object>> process(TreeNode<Group> groupNode, HttpServletRequest request) {
        TreeNode<Attributes<Object>> value = new TreeNode<>();
        value.setNode(groupNode.getNode());
        groupNode.getChildren().stream()
                .filter(it -> allowVisit(request, Authorization.VIEW, it.getNode()))
                .map(it -> process(it, request))   //递归调用process处理孩子结点
                .forEach(value::addChild);
        if (!Constants.ROOT_ID.equals(groupNode.getNode().getId())) {
            service
                    .listFiles(groupNode.getNode().getId())
                    .stream()
                    .filter(it -> allowVisit(request, Authorization.VIEW, it))
                    .map(MagicEntity::simple)
                    .map((Function<MagicEntity, TreeNode<Attributes<Object>>>) TreeNode::new)
                    .forEach(value::addChild);
        }
        return value;
    }

}
